﻿// ***********************************************************************
// Assembly         : STX.Service
// Author           : seven.x
// Created          : 12-26-2013
//
// Last Modified By : seven.x
// Last Modified On : 12-26-2013
// ***********************************************************************
// <copyright file="TAB_BlackListService.cs" company="驰创数码">
//     Copyright (c) 驰创数码. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using STX.Domain;
using STX.Lib.Net;
using STX.Repository;
using STX.Service.Valid.TabBlackListValid;

namespace STX.Service
{
    /// <summary>
    /// 黑名单功能
    /// </summary>
    public class TabBlackListService : BaseService<TabBlackList>
    {
        /// <summary>
        /// The numeric ip regex
        /// </summary>
        protected Regex NumericIpRegex = new Regex(@"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$");
        /// <summary>
        /// The wildcard ip regex
        /// </summary>
        protected Regex WildcardIpRegex = new Regex(@"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\*$");

        /// <summary>
        /// Gets or sets the add valid.
        /// </summary>
        /// <value>The add valid.</value>
        public Add AddValid { get; set; }

        #region 重写部分

        /// <summary>
        /// Adds the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="successAction"></param>
        /// <returns>System.Int64.</returns>
        public override long Add(TabBlackList entity, Action<ITransactionContext, TabBlackList> successAction = null)
        {
            Valid(entity, AddValid);
            var repository = Transaction.GetRepository<TabBlackList>();
            var models = repository.FindAll()
                                   .Where(o => o.IpAddress == entity.IpAddress);
            foreach (var model in models)
            {
                repository.Remove(model);
            }
            repository.Add(entity);
            Transaction.Commit();
            ClearBlackIpListCache();
            if (successAction != null)
                successAction(Transaction, entity);
            return entity.Id;
        }

        /// <summary>
        /// Deletes the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public override bool Remove(TabBlackList entity)
        {
            base.Remove(entity);
            ClearBlackIpListCache();
            return true;
        }

        /// <summary>
        /// Updates the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <exception cref="System.Exception">找不到此条数据</exception>
        public override bool Update(TabBlackList entity)
        {
            var model = FindModelById(entity.Id);
            if (model == null)
            {
                throw new Exception("找不到此条数据");
            }
            model.BlockScopeValue = entity.BlockScopeValue;
            model.EndTime = entity.EndTime;
            model.IpAddress = entity.IpAddress;
            model.StartTime = entity.StartTime;
            Transaction.Commit();
            ClearBlackIpListCache();
            return true;
        }

        #endregion



        /// <summary>
        /// 将当前会话加入黑名单
        /// </summary>
        /// <param name="bg">The BlockScope Enum.</param>
        /// <param name="days">The days.</param>
        public void AddCurrentToBlackList(TabBlackList.BlockScope bg, int days = 30)
        {
            var model = new TabBlackList
            {
                BlockScopeValue = (int)bg,
                StartTime = DateTime.Now,
                EndTime = DateTime.Now.AddDays(days),
                IpAddress = Ip.GetRealIP()
            };  
            Add(model);
        }

        /// <summary>
        /// 获取黑名单
        /// </summary>
        /// <value>The get black ip list.</value>
        public List<TabBlackList> GetBlackIpList
        {
            get
            {
                var cacheBlackIpList = CacheProvider.Get<List<TabBlackList>>("BlackIpList");
                if (cacheBlackIpList != null)
                {
                    return cacheBlackIpList;
                }

                var list = new List<TabBlackList>();
                var repository = Transaction.GetRepository<TabBlackList>();
                var query = repository.FindAll();
                foreach (var item in query)
                {
                    //纯数字
                    var numericIpMatch = NumericIpRegex.Match(item.IpAddress);
                    if (numericIpMatch.Success)
                    {
                        list.Add(item);
                    }

                    //带通配符(限最后一位)
                    var wildcardIpMatch = WildcardIpRegex.Match(item.IpAddress);
                    if (!wildcardIpMatch.Success) continue;
                    var newWildIpFormat = item.IpAddress.Replace("*", "{0}");
                    for (var i = 0; i <= 255; i++)
                    {
                        list.Add(new TabBlackList
                        {
                            BlockScopeValue = item.BlockScopeValue,
                            EndTime = item.EndTime,
                            StartTime = item.StartTime,
                            IpAddress = string.Format(newWildIpFormat, i)
                        });
                    }
                    CacheProvider.Set("BlackIpList", list);
                }
                return list;
            }
        }

        /// <summary>
        /// 检查当前上下文是否存在于黑名单中
        /// </summary>
        /// <param name="bg">The debug.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public bool CurrentIsInBlackIpList(TabBlackList.BlockScope bg)
        {
            var ip = Ip.GetRealIP();
            var blackList = GetBlackIpList;
            var query = from s in blackList
                        where ((TabBlackList.BlockScope)s.BlockScopeValue & bg) != 0
                                && s.IpAddress == ip
                                && s.StartTime <= DateTime.Now
                                && s.EndTime >= DateTime.Now
                        select s;
            return query.Any();
        }

        /// <summary>
        /// Clears the black ip list cache.
        /// </summary>
        public void ClearBlackIpListCache()
        {
            CacheProvider.Remove("BlackIpList");
        }
    }
}
